Skip to content

refactor: migrate cli-schema generation onto the published @cli-schema/* packages#474

Open
Mpdreamz wants to merge 3 commits into
elastic:mainfrom
Mpdreamz:fix/abstract-cli-schema
Open

refactor: migrate cli-schema generation onto the published @cli-schema/* packages#474
Mpdreamz wants to merge 3 commits into
elastic:mainfrom
Mpdreamz:fix/abstract-cli-schema

Conversation

@Mpdreamz

@Mpdreamz Mpdreamz commented Jul 13, 2026

Copy link
Copy Markdown
Member

Summary

Moves cli-schema generation off this repo's local implementation and onto three small npm
packages, published under the cli-schema npm organization:

This code used to live in this repo; now it's a dependency, maintained at
cli-schema/cli-schema-js.

These packages support CLIs that lazy-load their command tree natively — see the
commander package's README,
which is exactly this CLI's shape (only the invoked subtree gets fully built at startup for
dispatch performance).

The handler is a lot cleaner

Before, cli-schema.ts's handler had to build a synthetic command tree by hand, manually copy the
real program's global options onto it, and feed both into ~600 lines of local schema-building
logic we owned and had to maintain ourselves:

const schemaRoot = new Command(...)
for (const opt of rootProgram?.options ?? []) schemaRoot.addOption(opt)  // manual copy
// ...
return buildCliSchema(schemaRoot, globalOptions, version, noContextNames)  // our own ~600-line builder

After, the handler just says what's different about this CLI (a synthetic root, ES's flag
routing) and hands the rest to the package:

return buildCliSchema(schemaRoot, {
  // ...
  globalOptionsSource: rootProgram?.options,   // package knows what to do with this now
  enrichSchemaArg: enrichEsArg,
  postProcessInputParameter,
})

No more manual Command mutation, and no local schema-walking/hoisting logic left to maintain —
that's the package's job now.

Testing

All 1468 existing tests pass. docs/cli/schema.json is regenerated — parameter content is
unchanged, and it validates against the package's own schema validator. Lint/SPDX/notice/license
checks are clean.

Mpdreamz added 2 commits July 13, 2026 19:53
Retires this repo's local cli-schema.ts implementation in favor of
@cli-schema/spec, @cli-schema/zod, and @cli-schema/commander (extracted from
this exact codebase, published at github.com/cli-schema/cli-schema-js).

- factory.ts: the _commandConfig non-enumerable attach point is replaced with
  @cli-schema/commander's attachInput/attachIntent (the sole prior reader,
  cli-schema.ts, is the only thing that changes here -- runtime option/argument
  registration and request handling are untouched).
- lib/schema-args.ts: thin wrapper re-exporting @cli-schema/zod's generic
  extractor, adding back Elastic's found_in/sort-pairs enrichment and reserved
  flag list via the package's enrich/reserved hooks.
- cli-schema.ts: shrinks from ~600 lines to the ENVIRONMENT constant plus a
  handler that calls the package's buildCliSchema, passing classifyRole (to
  keep --dry-run as the only name-based role, matching prior emission),
  enrichSchemaArg, and postProcessInputParameter (for the body-routed CSV
  separator) -- all the local types/JSON-Schema helpers/walkers/hoisting logic
  the package now does are deleted.
- cli-schema-intent.ts: deleted; es/register.ts and kb/register.ts now import
  inferIntentFromHttp from @cli-schema/spec (byte-for-byte identical behavior).

This surfaced and fixed a real bug in @cli-schema/commander 0.1.0 (shipped as
0.1.1): every ES/KB command's Zod-schema-derived flags are registered as real
but *inaccurate* Commander options here (always optional, no Commander-visible
default, since actual required/default/enum enforcement happens via Zod after
merging flags with --input-file/stdin input) -- the package's old
"skip if a real option already covers this flag" rule silently discarded that
richer schema detail for nearly every parameter in this CLI. Fixed upstream via
a mergeParameter hook (schema wins on richness, Commander wins on
role/shortName/hidden) rather than picking one source over the other.

docs/cli/schema.json is regenerated, not byte-identical (root key order and
empty-array omission now follow the spec's canonical shape), but every
parameter's content is preserved exactly: 6915 parameters before and after,
identical counts for separator (50), repeatable (391), number (358), and enum
(61) fields, and the full document validates against @cli-schema/spec's own
meta-schema validator. The only 7 real diffs are ES's own native "dry_run"
query/body fields (e.g. cluster reroute, ILM migrate-to-data-tiers) gaining
role: "dryRun" instead of "flag" -- previously only the framework-injected
--dry-run flag got that classification; the merge fix applies the same
role-by-name heuristic uniformly regardless of which side registered the flag.

Added a regression test asserting the body-routed/query-routed separator
distinction survives end-to-end through the new wiring. Regenerated NOTICE.txt
for the three new bundled dependencies.
… support

Bumps @cli-schema/{spec,zod,commander} to ^0.2.0, which added two small,
generically-useful package APIs precisely to remove these workarounds:

- cli-schema.ts: buildCliSchema now takes globalOptionsSource (defaulting to
  root.options) for callers whose tree-discovery root isn't the same Command
  that has the real program's global options registered on it. schemaRoot no
  longer needs `.addOption()` copied onto it by hand -- it's built purely for
  command-tree assembly now, options included.

- lib/schema-args.ts: readMetaField was rebuilt upstream on the existing
  walkWrapperChain primitive, so it now does the full optional/default/
  lazy/union traversal instead of stopping one level in. schemaContainsId
  (used to detect ES's composite Sort type for the sort-pairs runtime parse
  style) shrinks from a hand-written predicate on walkWrapperChain to a
  one-line call to readMetaField -- the walkWrapperChain import is gone from
  this file entirely.

docs/cli/schema.json regenerates byte-identical (confirmed via
`git diff --exit-code`) -- both fixes change how the same data is derived,
not what's derived. All 1468 tests pass; lint/SPDX/notice/license checks
clean (NOTICE.txt regenerated for the version bump).
@github-actions

github-actions Bot commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

🔍 Preview links for changed docs

⏳ Building and deploying preview... View progress

This comment will be updated with preview links when the build is complete.

@Mpdreamz Mpdreamz changed the title Migrate cli-schema generation onto the published @cli-schema/* packages refactor: migrate cli-schema generation onto the published @cli-schema/* packages Jul 13, 2026
@JoshMock

Copy link
Copy Markdown
Member

@Mpdreamz can you resolve those conflicts? should be ready to merge after that.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants